Skip to content

chore(ci): gate PyPI publishing behind the production environment - #195

Merged
jfrench9 merged 1 commit into
mainfrom
chore/gate-publish-behind-approval
Aug 27, 2026
Merged

chore(ci): gate PyPI publishing behind the production environment#195
jfrench9 merged 1 commit into
mainfrom
chore/gate-publish-behind-approval

Conversation

@jfrench9

Copy link
Copy Markdown
Member

Summary

Publishing to PyPI now waits for a human: the publish job binds the production GitHub environment, whose protection rules (required reviewer; deployment refs release/* and main) gate every publish. Until now a push of a release/* branch — made by an automation token from create-release.yml — published immediately with no approval step, and a publish cannot be taken back.

Changes

  • .github/workflows/publish.ymlenvironment: production on the publish job, with a comment. Nothing else changes.
  • The environment and its rules already exist on this repository (configured 2026-08-27, same shape as the deploy gate on the platform and app repos).

Compatibility

No package or API change. The OIDC trusted publisher accepts any environment (publishes have succeeded with no environment declared, so the publisher carries no environment constraint), so no PyPI-side change is needed now; a later tightening can pin the PyPI publisher to this environment name. Release choreography is unchanged: create-release.yml bumps and pushes release/X.Y.Z; the publish run then waits for approval.

Testing

  • actionlint -shellcheck= .github/workflows/publish.yml — clean (with shellcheck on, only pre-existing SC2086/SC2129 notes in run: blocks this PR does not touch)
  • Not exercisable in-session; the next release is the first real run — the workflow will pause under Actions → the run → "Review deployments"

The publish job now binds the production GitHub environment, so its
protection rules (required reviewer, deployment refs) pause every
publish for approval. A release-branch push no longer publishes with no
human in the loop.
@jfrench9

Copy link
Copy Markdown
Member Author

@claude please review this PR

@claude

claude Bot commented Aug 27, 2026

Copy link
Copy Markdown

Claude encountered an error after 2s —— View job


I'll analyze this and get back to you.

@jfrench9
jfrench9 merged commit 498bf7a into main Aug 27, 2026
4 checks passed
@jfrench9
jfrench9 deleted the chore/gate-publish-behind-approval branch August 27, 2026 16:46
@jfrench9

Copy link
Copy Markdown
Member Author

@claude please review this PR — post-merge backfill: the review run failed on the previous token.

@claude

claude Bot commented Aug 27, 2026

Copy link
Copy Markdown

Claude finished @jfrench9's task in 46s —— View job


Review: gate PyPI publishing behind the production environment

  • Gather context (PR is merged; this is a post-merge backfill review — the earlier review run errored on a stale token)
  • Read the changed file (.github/workflows/publish.yml)
  • Review the change for correctness and risk
  • Post review feedback

Verdict: LGTM. This is a minimal, well-scoped CI change — a single environment: production key (+3 lines, a comment and the binding) on the publish job, nothing else touched.

What it does: binds the publish job to the production GitHub environment, so its protection rules (required reviewer, deployment-branch restriction to release/* and main) must pass before the job runs. Confirmed via create-release.yml/tag-release.yml:

  • create-release.yml pushes the release branch as release/${NEW_VERSION} (e.g. release/1.2.3), which matches the release/* deployment-branch pattern (single path segment, no nested slash) and the publish.yml trigger (push: branches: [release/**]).
  • This also now gates ad-hoc workflow_dispatch runs of publish.yml, not just the automated release/* push — that looks intentional given the PR's goal of requiring human approval for every publish path.

Compatibility claim checked: the PR body's assertion that the PyPI trusted publisher carries no environment constraint (so no PyPI-side change is needed) is consistent with prior publishes having succeeded with no environment declared at all — reasonable, though it's ultimately only verifiable by PyPI's trusted-publisher config, which isn't visible from this repo.

Risk: low and one-way-safe — this can only make publishing more restrictive (adds a required manual approval gate), never less. If the production environment or its reviewer/branch rules were misconfigured, the failure mode is "publish blocks," not "publish leaks/loosens," so it's a safe direction to ship even without being exercisable in-session (as the PR notes, actionlint -shellcheck= passed clean; the real test is the next release's Actions run pausing on "Review deployments").

No issues found — nothing to flag or fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant